﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Tools.DllImport;
using System.Runtime.InteropServices;

namespace System.Tools.Hook.Keyboard
{
    public class HookEvent:EventArgs
    {
         public int code;
         public int wParam;
         public int lParam;

         public HookEvent(int code, int wParam, int lParam)
         {
             this.code = code;
             this.wParam = wParam;
             this.lParam = lParam;
         }
    }

    public class HookKeyboard
    {      
        const int WH_KEYBOARD_LL = 13;  // Номер глобального LowLevel-хука на клавиатуру        
        const int WM_KEYDOWN = 0x100;   // Сообщения нажатия клавиши
        const int WM_KEYUP = 0x100;     // Сообщения нажатия клавиши

        public static event EventHandler<HookEvent> OnHook;

        public static event EventHandler<HookEvent> OnKeyDown;
        public static event EventHandler<HookEvent> OnKeyUp;

        private static User32.HookProc proc = hookProc;
        private static IntPtr hhook = IntPtr.Zero;

        public static void SetHook()
        {
            // Получаем handle нужной библиотеки
            IntPtr hInstance = Kernel32.LoadLibrary("User32");

            // Ставим LowLevel-hook, обработки клавиатуры, на все потоки
            hhook = User32.SetWindowsHookEx(WH_KEYBOARD_LL, proc, hInstance, 0);
        }

        public static void UnHook()
        {
            // Снятие хука
            User32.UnhookWindowsHookEx(hhook);
        }

        public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            try
            {                
                int vkCode = Marshal.ReadInt32(lParam);
                int vkParam = (int)wParam;

                if (OnHook != null) { OnHook(null, new HookEvent(code, vkParam, vkCode)); }

                if (vkParam == WM_KEYDOWN)
                {
                    if (OnKeyDown != null) { OnKeyDown(null, new HookEvent(code, vkParam, vkCode)); }
                }
                if (vkParam == WM_KEYUP)
                {
                    if (OnKeyUp != null) { OnKeyUp(null, new HookEvent(code, vkParam, vkCode)); }
                }
            }
            catch
            { 

            }
            finally
            {
                
            }

            return User32.CallNextHookEx(hhook, code, (int)wParam, lParam);       
        }
    }
}
